import React, { memo, useEffect, useState, useRef } from 'react'
import type { FC, ReactNode } from 'react'
import classNames from 'classnames'
import { useNavigate } from 'react-router-dom'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'

import CodeViewer from '../../components/Antd/CodeViewer'
import MarkDownViewer from '../../components/BytdViewer'
import ShareCard from '../../components/ShareCard'
import styles from './index.module.scss'
import '../../styles/iconfont.css'
import {
  useMySelector,
  useMyDispatch,
  resetAllStore,
  MyShallEqual
} from '../../store'
import { setShareOrEdit } from '../../store/modules/success'
import { setIsOpen, setPassword } from '../../store/modules/create'
import fetchData from '../../request'

interface IProps {
  children?: ReactNode
}

interface codeAllType {
  label: string
  key: string
  language: string
  codeSlice: string
}

const Successcreate: FC<IProps> = () => {
  const {
    title,
    currentTime,
    endTime,
    shareOrEdit,
    isOpen,
    label,
    copyCode,
    foucsLanguage,
    id,
    codeAll
  } = useMySelector(
    (state) => ({
      title: state.code.title,
      currentTime: state.code.currentTime,
      endTime: state.code.endTime,
      shareOrEdit: state.success.shareOrEdit,
      isOpen: state.code.isOpen,
      label: state.code.label,
      copyCode: state.success.copyCode,
      foucsLanguage: state.success.focusLanguage,
      id: state.codeall.id,
      codeAll: state.codeall.codeAll as codeAllType[]
    }),
    MyShallEqual
  )
  const dispatch = useMyDispatch()
  const [focusShareOrDownload, setFocusShareOrDownload] = useState(true)
  const [highLightRight, sethighLightRight] = useState(false)
  const [highLightLeft, sethighLightLeft] = useState(false)
  const [moreSettings, setMoreSettings] = useState(false)
  const [passwordInput, setPasswordInput] = useState('')
  const [mb1, setMB1] = useState(false)
  const [mb2, setMB2] = useState(false)
  const [mb3, setMB3] = useState(false)
  const pointRef = useRef<HTMLDivElement | null>(null)
  const moreRef = useRef<HTMLDivElement | null>(null)
  let timeRight: NodeJS.Timeout | null = null
  let timeLeft: NodeJS.Timeout | null = null
  const navigate = useNavigate()

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        pointRef.current &&
        moreRef.current &&
        !pointRef.current.contains(event.target as Node) &&
        !moreRef.current.contains(event.target as Node)
      ) {
        setMoreSettings(false)
      }
    }

    if (moreSettings) document.addEventListener('mousedown', handleClickOutside)
    else document.removeEventListener('mousedown', handleClickOutside)

    return () => {
      document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [moreSettings])

  const copyText = async (content: string) => {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(content)
    } else {
      const textArea = document.createElement('textarea')
      textArea.value = content
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()
      document.execCommand('copy')
      document.body.removeChild(textArea)
    }
  }
  const fuzhi = () => {
    copyText(copyCode)
  }

  const handleMouseEnter = (
    event: React.MouseEvent<HTMLDivElement>,
    direction: string
  ) => {
    event.stopPropagation()
    if (direction === 'right' && shareOrEdit) {
      sethighLightRight(true)
      if (timeRight) {
        clearTimeout(timeRight)
      }
    }
    if (direction === 'left' && focusShareOrDownload) {
      sethighLightLeft(true)
      if (timeLeft) {
        clearTimeout(timeLeft)
      }
    }
  }

  const handleMouseLeave = (direction: string) => {
    if (direction === 'right') {
      timeRight = setTimeout(() => {
        sethighLightRight(false)
      }, 500)
    }
    if (direction === 'left') {
      timeLeft = setTimeout(() => {
        sethighLightLeft(false)
      }, 500)
    }
  }

  const handleClickRight = (
    e: React.MouseEvent<HTMLDivElement>,
    flag: boolean
  ) => {
    if (flag) {
      dispatch(setShareOrEdit(true))
      sethighLightRight(true)
    } else {
      dispatch(setShareOrEdit(false))
    }
  }

  const handleClickLeft = (
    e: React.MouseEvent<HTMLDivElement>,
    flag: boolean
  ) => {
    if (flag) {
      setFocusShareOrDownload(true)
      sethighLightLeft(true)
    } else {
      setFocusShareOrDownload(false)
    }
  }

  const downloadCode = () => {
    const languageToMimeTypeMap: { [key: string]: string } = {
      javascript: '.js',
      typescript: '.ts',
      html: '.html',
      css: '.css',
      json: '.json',
      java: '.java',
      c: '.c',
      python: '.py',
      scss: '.scss',
      markdown: '.md',
      go: '.go'
    }

    const zip = new JSZip()

    codeAll.forEach((item) => {
      let fileExtension: string = ''
      if (item.language === 'C++') {
        fileExtension = '.cpp'
      } else if (item.language === 'C#') {
        fileExtension = '.cs'
      } else {
        fileExtension = languageToMimeTypeMap[item.language.toLowerCase()] || ''
      }

      zip.file(item.label + fileExtension, item.codeSlice)

      // 不用压缩包，直接下载的方式
      // const blob = new Blob([item.codeSlice], { type: 'txt' })
      // const url = window.URL.createObjectURL(blob)
      // const a = document.createElement('a')
      // a.href = url
      // a.download = item.label + fileExtension
      // document.body.appendChild(a)
      // a.click()
      // document.body.removeChild(a)
      // window.URL.revokeObjectURL(url)
    })
    zip.generateAsync({ type: 'blob' }).then((content) => {
      saveAs(content, 'code.zip')
    })
  }

  return (
    <div className={classNames(styles.container)}>
      <div className={styles.title}>
        <div className={styles.red}></div>
        <div className={styles.yellow}></div>
        <div className={styles.green}></div>
        <span className={styles.text}>{title}</span>
        <div
          className={classNames(
            'iconfont',
            isOpen ? 'icon-jiesuosuo' : 'icon-suo',
            styles.suo
          )}
        ></div>
        <div className={classNames(styles.rightControls)}>
          <div
            className={classNames(
              'iconfont',
              'icon-fenxiang',
              styles.sharing,
              shareOrEdit && styles.isFocus
            )}
            onClick={(e) => {
              handleClickRight(e, true)
            }}
            onMouseEnter={(e) => handleMouseEnter(e, 'right')}
            onMouseLeave={() => handleMouseLeave('right')}
          >
            分享
          </div>
          <div
            className={classNames(
              styles.editor,
              !shareOrEdit && styles.isFocus
            )}
            onClick={(e) => {
              handleClickRight(e, false)
              navigate('/create')
            }}
          >
            编辑
          </div>
        </div>
      </div>
      <div className={classNames(styles.markdownViewer)}>
        <MarkDownViewer />
      </div>
      <div className={classNames(styles.codeSelect)}>
        <CodeViewer />
        <div className={classNames(styles.language)}>
          {foucsLanguage ? foucsLanguage : '未指定语言'}
        </div>
      </div>
      {/* <EditorViewer /> */}
      <div
        className={classNames('iconfont', 'icon-fuzhi', styles.fuzhi)}
        onClick={() => fuzhi()}
      ></div>

      <div className={classNames(styles.footer)}>
        <div className={classNames(styles.top)}>
          <div className={classNames(styles.leftLabel)}>
            <span>{isOpen ? '公开' : '加密'}</span>
            {label && label.length > 0 ? (
              label.map((value, index) => {
                return <span key={index}>{value}</span>
              })
            ) : (
              <span>未选择代码标签</span>
            )}
          </div>
          <div className={classNames(styles.endTime)}>过期时间:{endTime}</div>
        </div>
        <div className={classNames(styles.bottom)}>
          <div className={classNames(styles.startTime)}>
            创建于:{currentTime}
          </div>
          <div
            className={classNames(
              'iconfont',
              'icon-sangediandian',
              styles.point
            )}
            onClick={() => {
              setMoreSettings(true)
            }}
            ref={pointRef}
          ></div>
        </div>
      </div>

      <div className={classNames(styles.sideControls)}>
        <div
          className={classNames(
            'iconfont',
            'icon-fenxiang',
            styles.fenxiang,
            focusShareOrDownload && styles.isActive
          )}
          onClick={(e) => {
            handleClickLeft(e, true)
          }}
          onMouseEnter={(e) => handleMouseEnter(e, 'left')}
          onMouseLeave={() => handleMouseLeave('left')}
        ></div>
        <span>分享</span>
        <div
          className={classNames(
            'iconfont',
            'icon-download',
            styles.download,
            !focusShareOrDownload && styles.isActive
          )}
          onClick={(e) => {
            handleClickLeft(e, false)
            downloadCode()
          }}
        ></div>
        <span>下载</span>
      </div>

      <div
        className={classNames(
          highLightLeft || highLightRight || styles.hide,
          highLightRight && styles.shareCardRight,
          highLightLeft && styles.shareCardLeft
        )}
        onMouseEnter={(e) => {
          if (highLightRight) handleMouseEnter(e, 'right')
          else if (highLightLeft) handleMouseEnter(e, 'left')
        }}
        onMouseLeave={() => {
          if (highLightRight) handleMouseLeave('right')
          else if (highLightLeft) handleMouseLeave('left')
        }}
      >
        <ShareCard />
      </div>

      <div
        className={classNames(styles.mengban1, mb1 && styles.mengban1Active)}
      >
        <div className={classNames(styles.menban1content)}>
          <div
            className={classNames('iconfont', 'icon-jiesuosuo', styles.jiesuo)}
          ></div>
          <span>取消加密</span>
          <div className={styles.opencode}>取消加密，代码将会公开</div>
          <div className={classNames(styles.button2)}>
            <div
              className={styles.cancel}
              onClick={() => {
                setMB1(false)
              }}
            >
              取消
            </div>
            <div
              className={styles.confirm}
              onClick={async () => {
                setMB1(false)
                dispatch(setIsOpen(true))
                await fetchData('/update', { id, isOpen: true }, 'POST')
              }}
            >
              确定
            </div>
          </div>
        </div>
      </div>

      <div
        className={classNames(styles.mengban2, mb2 && styles.mengban2Active)}
      >
        <div className={styles.mengban2content}>
          <div className={classNames('iconfont', 'icon-suo', styles.suo)}></div>
          <span>加密</span>
          <div className={styles.inputD}>
            <input
              type="password"
              value={passwordInput}
              onChange={(e) => {
                setPasswordInput(e.target.value)
              }}
            />
          </div>
          <div className={classNames(styles.button2)}>
            <div
              className={styles.cancel}
              onClick={() => {
                setMB2(false)
              }}
            >
              取消
            </div>
            <div
              className={styles.confirm}
              onClick={async () => {
                if (passwordInput.length > 8 || passwordInput.length < 4) {
                  alert('密码长度应该是4-8位')
                  return
                }
                setMB2(false)
                dispatch(setPassword(passwordInput))
                dispatch(setIsOpen(false))
                setPasswordInput('')
                await fetchData(
                  '/update',
                  { id, isOpen: false, password: passwordInput },
                  'POST'
                )
              }}
            >
              确定
            </div>
          </div>
        </div>
      </div>

      <div
        className={classNames(styles.mengban3, mb3 && styles.mengban3Active)}
      >
        <div className={styles.mengban3content}>
          <div
            className={classNames('iconfont', 'icon-jinggao', styles.jinggao)}
          ></div>
          <span>是否确认删除? 不可找回</span>
          <div
            className={classNames(styles.button2)}
            onClick={() => {
              setMB3(false)
            }}
          >
            <div className={styles.cancel}>取消</div>
            <div
              className={styles.confirm}
              onClick={async () => {
                await fetchData('/delete', { id }, 'POST')
                dispatch(resetAllStore())
                navigate('/create')
              }}
            >
              确定
            </div>
          </div>
        </div>
      </div>

      <div
        className={classNames(
          styles.pointContent,
          moreSettings && styles.pointContentActive
        )}
        ref={moreRef}
      >
        <div
          className={styles.pointItem}
          onClick={() => {
            if (isOpen) {
              setMB2(true)
            } else {
              setMB1(true)
            }
          }}
        >
          <div
            className={classNames(
              'iconfont',
              isOpen ? 'icon-suo' : 'icon-jiesuosuo',
              styles.icon
            )}
          ></div>
          <div className={styles.text}>{isOpen ? '加密' : '取消加密'}</div>
        </div>
        <div
          className={styles.pointItem}
          onClick={() => {
            navigate('/create')
          }}
        >
          <div
            className={classNames('iconfont', 'icon-bianji', styles.icon)}
          ></div>
          <div className={styles.text}>编辑</div>
        </div>
        <div className={styles.pointItem} onClick={() => setMB3(true)}>
          <div
            className={classNames('iconfont', 'icon-shanchu', styles.icon)}
          ></div>
          <div className={styles.text}>删除</div>
        </div>
      </div>
    </div>
  )
}

export default memo(Successcreate)
